const isArrayType = (array) => {
  if (array instanceof Array) {
    return;
  } else {
    throw new Error('类型错误');
  }
}
const sortDirection = {
  desc: 'desc',
  asc: 'asc',
};
/**
 * 冒泡排序
 * @param {array} array 数组
 * @param {desc,asc} direction 正序逆序
 */
const bubble = function* (array, direction = sortDirection.desc) {
  isArrayType(array);
  array = [...array];
  for (let i = 0; i < array.length - 1; i++) {
    for (let j = 0; j < array.length - 1 - i; j++) {
      const element1 = Number.parseInt(array[j]);
      const element2 = Number.parseInt(array[j + 1]);
      yield [j, j + 1, array];
      if (element1 > element2 && direction === sortDirection.asc) {
        [array[j], array[j + 1]] = [array[j + 1], array[j]];
      } else if (element1 < element2 && direction === sortDirection.desc) {
        [array[j], array[j + 1]] = [array[j + 1], array[j]];
      }
      yield [j, j + 1, array];
    }
  }
  return;
}

const select = function* (array, direction = sortDirection.desc) {
  isArrayType(array);
  array = [...array];
  for (let i = 0; i < array.length - 1; i++) {
    for (let j = i + 1; j < array.length; j++) {
      const element1 = Number.parseInt(array[i]);
      const element2 = Number.parseInt(array[j]);
      yield [i, j, array];
      if (element1 > element2 && direction === sortDirection.asc) {
        [array[i], array[j]] = [array[j], array[i]];
      } else if (element1 < element2 && direction === sortDirection.desc) {
        [array[i], array[j]] = [array[j], array[i]];
      }
      yield [i, j, array];
    }
  }
  return;
}
const insert = function* (array, direction = sortDirection.desc) {
  isArrayType(array);
  array = [...array];
  for (let i = 1; i < array.length; i++) {
    const current = Number.parseInt(array[i]);
    let index = i;
    for (let j = i - 1; j >= 0; j--) {
      const pre = Number.parseInt(array[j]);
      yield [index, j, array];
      if ((pre > current && direction === sortDirection.asc)
        || (pre < current && direction === sortDirection.desc)) {
        [array[index], array[j]] = [array[j], array[index]];
        yield [index, j, array];
        index = j;
      } else if ((pre >= current && direction === sortDirection.desc)
        || (pre <= current && direction === sortDirection.asc)) {
        break;
      }
    }
  }
  return;
}

const quick = function* (array, direction = sortDirection.desc) {
  isArrayType(array);
  array = [...array];
  const length = array.length;
  if (length < 2) {
    return array;
  }
  const base = Number.parseInt(array[0]);
  let left = 0;
  let right = length - 1;
  let flag = true;
  // let index = right;
  while (left < right) {
    yield [left, right, array];
    const element = Number.parseInt(flag ? array[right] : array[left]);
    if (element < base) {
      array[flag ? right : left] = element;
      flag = !flag;
    }
    yield [left, right, array];
    if (flag) {
      right--;
    } else {
      left++;
    }
  }
  return ;
}
export default {
  bubble,
  select,
  insert,
  quick,
  sortDirection,
};